/** =====================================================
 * Copyright © hk. 2022-2025. All rights reserved.
 * File name  : 06_rtc_demo.c
 * Author     : 上上签
 * Date       : 2023-12-09
 * Version    : 
 * Description: 
 * ======================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <aos/kernel.h>
#include <k_api.h>
#include "aos/init.h"
#include "board.h"

#include "ulog/ulog.h"
#include "aos/cli.h"

#include "aos/hal/gpio.h"
#include "aos/hal/rtc.h"

#define RED_LED     0 // PA14
#define GRE_LED     1 // PA15
#define MODULE_NAME "rtc_app" /* module name used by ulog */
#define PORT_RTC_0  0
static gpio_dev_t  led_gpio_dev[2] = {0}; 
static rtc_dev_t rtc0;
aos_timer_t *pAlarmTimer = NULL;
typedef struct __ALARM_TIME_
{
    int hours;
    int minute;
    int second;
}ALARM_TIME;

static ALARM_TIME alarm_time = {0}; 

int led_init(void)
{
    //由于PA14时rtl8710的jtag接口，我要使用GPIO功能，必须先关闭jtag借口
    sys_jtag_off();
    led_gpio_dev[0].port = RED_LED;
    led_gpio_dev[0].config = OUTPUT_PUSH_PULL;
    led_gpio_dev[0].priv = NULL;
    //gpio PA14初始化
    hal_gpio_init(&led_gpio_dev[0]);

    led_gpio_dev[1].port = GRE_LED;
    led_gpio_dev[1].config = OUTPUT_PUSH_PULL;
    led_gpio_dev[1].priv = NULL;
    //gpio PA14初始化
    hal_gpio_init(&led_gpio_dev[1]);

    return 0;
}

void hal_rtc_app_init(void)
{
    int ret = -1;

    rtc_config_t rtc_cfg;
    rtc_time_t   time_buf;

    /* rtc port set */
    rtc0.port = PORT_RTC_0;

    /* set to DEC format */
    rtc0.config.format = HAL_RTC_FORMAT_DEC;

    /* init rtc0 with the given settings */
    ret = hal_rtc_init(&rtc0);
    if (ret != 0) {
        printf("rtc init error !\n");
        return;
    }

    time_buf.sec     = 0;
    time_buf.min     = 49;
    time_buf.hr      = 10;
    time_buf.weekday = 6;
    time_buf.date    = 9;
    time_buf.month   = 12;
    time_buf.year    = 2023;

    /* set rtc0 time to 2020/2/26,21:31:00 */
    ret = hal_rtc_set_time(&rtc0, &time_buf);
    if (ret != 0) {
        printf("rtc0 set time error !\n");
        return;
    }
    printf("set time is: %4d-%02d-%02d %02d:%02d:%02d\r\n", time_buf.year, time_buf.month,
           time_buf.date, time_buf.hr, time_buf.min, time_buf.sec);
}

void hal_rtc_app_gettime(void)
{
    int        ret = -1;
    rtc_time_t time_buf;

    /* get current time */
    ret = hal_rtc_get_time(&rtc0, &time_buf);
    if (ret != 0) {
        printf("get time error !\n");
        return;
    }

    printf("current time is: %4d-%02d-%02d %02d:%02d:%02d\r\n", time_buf.year, time_buf.month,
           time_buf.date, time_buf.hr, time_buf.min, time_buf.sec);
}

/**
 * timer callback function.
 * The current use case is executed every 1300ms.
 */
static void timer1_func(void *timer, void *arg)
{
    if(pAlarmTimer == NULL)
    {
        LOGE(MODULE_NAME, "pAlarmTimer is null!");
        return;
    }
    /*
    * Warning: an interface that causes a block is not allowed to be called within this function.
    * Blocking within this function will cause other timers to run incorrectly.
    * The printf function may also block on some platforms, so be careful how you call it.
    */
    LOGI(MODULE_NAME, "[timer_new]timer expires!");
    aos_timer_stop(pAlarmTimer);//只运行一次
}

static uint32_t count_alarm_interval(ALARM_TIME alarmTime)
{
    int ret = -1;
    int32_t alarm_time_tick = 0;
    int32_t real_time_tick = 0;
    rtc_time_t time_buf = {0};

    /* get current time */
    ret = hal_rtc_get_time(&rtc0, &time_buf);
    if (ret != 0) 
    {
        printf("get time error !\n");
        return;
    }
    //计算闹钟和当前时间对应的ms数
    alarm_time_tick = alarmTime.hours*60*60*1000+alarmTime.minute*60*1000+alarmTime.second*1000;
    real_time_tick = time_buf.hr*60*60*1000+time_buf.min*60*1000+time_buf.sec*1000;
    printf("alarm_time_tick=%dms real_time_tick=%dms\r\n", alarm_time_tick, real_time_tick);
    //判断闹钟是否大于当前的实时时钟
    if(alarm_time_tick - real_time_tick >= 0)
    {
        return (alarm_time_tick - real_time_tick);//闹钟-实时时钟的差值
    }
    else
    {
        return (24*60*60*1000 + real_time_tick - alarm_time_tick);//一天ms数+实时时钟-闹钟
    }
}

static void timer_time_change(int nms)
{
    if(pAlarmTimer == NULL)
    {
        LOGE(MODULE_NAME, "pAlarmTimer is null!");
        return;
    }
    /* stop the timer before modifying the timer parameter */
    aos_timer_stop(pAlarmTimer);

    /* the timer cycle is modified to nms */
    aos_timer_change(pAlarmTimer, nms);

    /* start the timer after the timer parameter modification is complete */
    aos_timer_start(pAlarmTimer);
}

static void date_help_show(void)
{
	printf("Usage: date [OPTIONS] COMMAND [ARGS]\r\n");
	printf("\r\n");
	printf("Options:\r\n");
	printf("help        :  show date help\r\n");
	printf("\r\n");
	printf("Command:\r\n");
	printf("-r          :  read date\n");
	printf("-s          :  set date\r\n");
	printf("date -s Args: \r\n");
    printf("Arags       :  xx:xx:xx\r\n");
}

static void alarm_help_show(void)
{
	printf("Usage: alarm [OPTIONS] COMMAND [ARGS]\r\n");
	printf("\r\n");
	printf("Options:\r\n");
	printf("help        :  show alarm help\r\n");
	printf("\r\n");
	printf("Command:\r\n");
	printf("-r          :  read alarm\n");
	printf("-s          :  set alarm\r\n");
	printf("alarm -s Args: \r\n");
    printf("Arags       :  xx:xx:xx\r\n");
}

static void date_cmd(char *buf, int32_t len, int32_t argc, char **argv)
{
    int ret = 0;
    rtc_time_t time_buf = {0};
    char *ptimeIndex = NULL;
    char s_Hours[20] = {0};
    char s_Minutes[20] = {0};
    char s_Seconds[20] = {0};

    if(argc == 2)
    {
        if(strcmp(argv[0], "date"))
		{
			printf("cmd is error!plese retry!\r\n");
			return ;
		}

		if(strcmp(argv[1], "help") == 0)
		{
			date_help_show();
		}
		else if(strcmp(argv[1], "-r") == 0)
		{
			//read date
            ret = hal_rtc_get_time(&rtc0, &time_buf);
			if (ret != 0) {
                printf("get time error !\n");
                return;
            }

            printf("current time is: %4d-%02d-%02d %02d:%02d:%02d\r\n", 
                    time_buf.year, time_buf.month, time_buf.date, 
                    time_buf.hr, time_buf.min, time_buf.sec);
		}
		else
		{
			printf("date argv error!plese retry!\r\n");
			return;
		}
    }
    else if(argc == 3)
    {
        if(strcmp(argv[0], "date"))
		{
			printf("cmd is error!plese retry!\r\n");
			return ;
		}

        if(strcmp(argv[1], "-s") != 0)
        {
            printf("cmd is error!plese retry!\r\n");
			return ;
        }
        else
        {
            //小时
            ptimeIndex = strtok(argv[2], ":");
            memcpy(s_Hours, ptimeIndex, strlen(ptimeIndex));
            //分钟
            ptimeIndex = strtok(NULL, ":");
            memcpy(s_Minutes, ptimeIndex, strlen(ptimeIndex));
            //秒
            ptimeIndex = strtok(NULL, ":");
            memcpy(s_Seconds, ptimeIndex, strlen(ptimeIndex));
            //组合时间
            time_buf.sec     = atoi((const char*)s_Seconds);
            time_buf.min     = atoi((const char*)s_Minutes);
            time_buf.hr      = atoi((const char*)s_Hours);
            time_buf.weekday = 6;
            time_buf.date    = 9;
            time_buf.month   = 12;
            time_buf.year    = 2023;

            /* set rtc0 time to 2020/2/26,21:31:00 */
            ret = hal_rtc_set_time(&rtc0, &time_buf);
            if (ret != 0) {
                printf("rtc0 set time error !\n");
                return;
            }
            printf("set time is: %4d-%02d-%02d %02d:%02d:%02d\r\n", time_buf.year, time_buf.month,
                time_buf.date, time_buf.hr, time_buf.min, time_buf.sec);
        }
    }
    else
	{
		printf("input argument error!plese retry!\r\n");
        date_help_show();
	}
}

static void alarm_cmd(char *buf, int32_t len, int32_t argc, char **argv)
{
    int ret = 0;
    rtc_time_t time_buf = {0};
    char *ptimeIndex = NULL;
    char s_Hours[20] = {0};
    char s_Minutes[20] = {0};
    char s_Seconds[20] = {0};
    uint32_t alarm_tick = 0;
    if(argc == 2)
    {
        if(strcmp(argv[0], "alarm"))
		{
			printf("cmd is error!plese retry!\r\n");
			return ;
		}

		if(strcmp(argv[1], "help") == 0)
		{
			date_help_show();
		}
		else if(strcmp(argv[1], "-r") == 0)
		{
            printf("alarm time is: %02d:%02d:%02d\r\n",  
                    alarm_time.hours, alarm_time.minute, alarm_time.second);
		}
		else
		{
			printf("alarm argv error!plese retry!\r\n");
			return;
		}
    }
    else if(argc == 3)
    {
        if(strcmp(argv[0], "alarm"))
		{
			printf("cmd is error!plese retry!\r\n");
			return ;
		}

        if(strcmp(argv[1], "-s") != 0)
        {
            printf("cmd is error!plese retry!\r\n");
			return ;
        }
        else
        {
            //小时
            ptimeIndex = strtok(argv[2], ":");
            memcpy(s_Hours, ptimeIndex, strlen(ptimeIndex));
            //分钟
            ptimeIndex = strtok(NULL, ":");
            memcpy(s_Minutes, ptimeIndex, strlen(ptimeIndex));
            //秒
            ptimeIndex = strtok(NULL, ":");
            memcpy(s_Seconds, ptimeIndex, strlen(ptimeIndex));
            //组合时间
            alarm_time.second = atoi((const char*)s_Seconds);
            alarm_time.minute = atoi((const char*)s_Minutes);
            alarm_time.hours = atoi((const char*)s_Hours);

            printf("alarm time set is %02d:%02d:%02d\r\n",
                    alarm_time.hours,alarm_time.minute,alarm_time.second);

            alarm_tick = count_alarm_interval(alarm_time);

            printf("alarm_tick=%d\r\n", alarm_tick);

            if(pAlarmTimer == NULL)
            {
                pAlarmTimer = aos_malloc(sizeof(aos_timer_t));
                if(pAlarmTimer)
                {
                    ret = aos_timer_new(pAlarmTimer, timer1_func, NULL, alarm_tick, 1);
                    if (ret != 0) 
                    {
                        LOGE(MODULE_NAME, "create timer error!");
                        return;
                    }
                }
            }
            else
            {
                timer_time_change(alarm_tick);
                printf("timer_time_change alarm_tick=%d\r\n", alarm_tick);
            }

        }
    }
    else
	{
		printf("input argument error!plese retry!\r\n");
        alarm_help_show();
	}
}

void cmd_init(void)
{
	int ret;
	static struct cli_command cmds[] = {
		{"date","date read && set", date_cmd},
		{"alarm","alarm read && set", alarm_cmd},
	};
	
	ret = aos_cli_register_commands(cmds, sizeof(cmds)/sizeof(cmds[0]));
	if(ret != 0)
	{
		printf("cli register error!\r\n");
	}
}

int application_start(int argc, char *argv[])
{
    int ret = 0;
    int index = 0;

    led_init();

    aos_set_log_level(AOS_LL_INFO);

    aos_cli_init();
    cmd_init();
    hal_rtc_app_init();
    while(1)
    {
        aos_msleep(1000);
        hal_gpio_output_toggle(&led_gpio_dev[1]);
    }
  
}
